package com.engine.kq.cmd.report;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.engine.common.biz.AbstractCommonCommand;
import com.engine.common.entity.BizLogContext;
import com.engine.core.interceptor.CommandContext;
import com.engine.kq.biz.*;
import com.engine.kq.cmd.shiftmanagement.toolkit.ShiftManagementToolKit;
import com.engine.kq.util.ExcelUtil;
import com.engine.kq.util.KQDurationCalculatorUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import weaver.common.DateUtil;
import weaver.conn.RecordSet;
import weaver.general.TimeUtil;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.hrm.company.DepartmentComInfo;
import weaver.hrm.company.SubCompanyComInfo;
import weaver.hrm.job.JobTitlesComInfo;
import weaver.hrm.resource.ResourceComInfo;
import weaver.systeminfo.SystemEnv;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class ExportDailyExcelCmd extends AbstractCommonCommand<Map<String, Object>> {

  private HttpServletRequest request;
  private HttpServletResponse response;
  private List<String> lsFieldDataKey;

  public ExportDailyExcelCmd(Map<String, Object> params, HttpServletRequest request, HttpServletResponse response, User user) {
    this.user = user;
    this.params = params;
    this.request = request;
    this.response = response;
    this.lsFieldDataKey = new ArrayList<>();
  }

  @Override
  public Map<String, Object> execute(CommandContext commandContext) {
    Map<String, Object> retmap = new HashMap<String, Object>();
    RecordSet rs = new RecordSet();
    String sql = "";
    try {
      SubCompanyComInfo subCompanyComInfo = new SubCompanyComInfo();
      DepartmentComInfo departmentComInfo = new DepartmentComInfo();
      ResourceComInfo resourceComInfo = new ResourceComInfo();
      JobTitlesComInfo jobTitlesComInfo = new JobTitlesComInfo();
      ShiftManagementToolKit shiftManagementToolKit = new ShiftManagementToolKit();
      KQWorkTime kqWorkTime = new KQWorkTime();
      KQReportBiz kqReportBiz = new KQReportBiz();
      KQLeaveRulesBiz kqLeaveRulesBiz = new KQLeaveRulesBiz();
      KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo();
      String leavetype_is_on = Util.null2String(kqSettingsComInfo.getMain_val("leavetype_is_on"),"0");

      new KQReportBiz().insertKqReportExportLog(params, user);
      JSONObject jsonObj = JSON.parseObject(Util.null2String(params.get("data")));
      String attendanceSerial = Util.null2String(jsonObj.get("attendanceSerial"));
      String fromDate = Util.null2String(jsonObj.get("fromDate"));
      String toDate = Util.null2String(jsonObj.get("toDate"));
      String typeselect =Util.null2String(jsonObj.get("typeselect"));
      if(typeselect.length()==0)typeselect = "3";
      if(!typeselect.equals("") && !typeselect.equals("0")&& !typeselect.equals("6")){
        if(typeselect.equals("1")){
          fromDate = TimeUtil.getCurrentDateString();
          toDate = TimeUtil.getCurrentDateString();
        }else{
          fromDate = TimeUtil.getDateByOption(typeselect,"0");
          toDate = TimeUtil.getDateByOption(typeselect,"1");
        }
      }
      //人员状态
      String status = Util.null2String(jsonObj.get("status"));
      String subCompanyId = Util.null2String(jsonObj.get("subCompanyId"));
      String departmentId = Util.null2String(jsonObj.get("departmentId"));
      String resourceId = Util.null2String(jsonObj.get("resourceId"));
      String allLevel = Util.null2String(jsonObj.get("allLevel"));
      String isNoAccount = Util.null2String(jsonObj.get("isNoAccount"));
      String viewScope = Util.null2String(jsonObj.get("viewScope"));
      List<String> showColumns = Util.splitString2List(Util.null2String(jsonObj.get("showColumns")),",");
      showColumns.add("lastname");
      showColumns.add("kqdate");
      showColumns.add("serialid");
      showColumns.removeIf(showColumn->showColumn.trim().equals(""));

      List<String> tmpShowColumns = new ArrayList<>();
      for(String showColumn:showColumns){
        tmpShowColumns.add(showColumn);
        String cascadekey = "";
        if(showColumn.equals("signin1")){
          cascadekey = "signout1";
        }else if(showColumn.equals("signin2")){
          cascadekey = "signout2";
        }else if(showColumn.equals("signin3")){
          cascadekey = "signout3";
        }else if(showColumn.equals("beLate")){
          cascadekey = "beLateMins";
        }else if(showColumn.equals("leaveEearly")){
          cascadekey = "leaveEarlyMins";
        }else if(showColumn.equals("graveBeLate")){
          cascadekey = "graveBeLateMins";
        }else if(showColumn.equals("graveLeaveEarly")){
          cascadekey = "graveLeaveEarlyMins";
        }else if(showColumn.equals("absenteeism")){
          cascadekey = "absenteeismMins";
        }else if(showColumn.equals("overtime")){
          tmpShowColumns.add("overtime_4leave");
          tmpShowColumns.add("overtime_nonleave");
          tmpShowColumns.add("workingDayOvertime_nonleave");
          tmpShowColumns.add("workingDayOvertime_4leave");
          tmpShowColumns.add("restDayOvertime_nonleave");
          tmpShowColumns.add("restDayOvertime_4leave");
          tmpShowColumns.add("holidayOvertime_4leave");
          tmpShowColumns.add("holidayOvertime_nonleave");
        }
        if(cascadekey.length()>0){
          tmpShowColumns.add(cascadekey);
        }
      }
      showColumns = tmpShowColumns;

      String today = DateUtil.getCurrentDate();
      if(DateUtil.compDate(today, toDate)>0){//结束如期不大于今天
        toDate = today;
      }

      String rightSql = new KQReportBiz().getReportRight("2",""+user.getUID(),"a");

      LinkedHashMap<String, Object> workbook = new LinkedHashMap<>();
      List<Object> lsSheet = new ArrayList<>();
      Map<String, Object> sheet = null;
      List<Object> titleList = new ArrayList<>();
      Map<String,Object> title = null;
      List<List<Object>> dataList = new ArrayList<>();
      List<Object> data = null;
      List<Map<String,Object>> constraintList = null;
      Map<String,Object> constraint = null;

      sheet = new HashMap<>();
      sheet.put("sheetName", SystemEnv.getHtmlLabelName(	390352, user.getLanguage()));
      sheet.put("sheetTitle", SystemEnv.getHtmlLabelName(	390352, user.getLanguage()));

      List<Map<String, Object>> leaveRules = kqLeaveRulesBiz.getAllLeaveRules();

      Map<String,Object> mapChildColumnInfo = null;
      List<Object> childColumns = null;
      KQReportFieldComInfo kqReportFieldComInfo = new KQReportFieldComInfo();
      while (kqReportFieldComInfo.next()){
        if(Util.null2String(kqReportFieldComInfo.getParentid()).length()>0)continue;
        if(!kqReportFieldComInfo.getReportType().equals("all") && !kqReportFieldComInfo.getReportType().equals("daily"))continue;
        if (!showColumns.contains(kqReportFieldComInfo.getFieldname())&&!showColumns.contains(kqReportFieldComInfo.getParentid())) continue;
        if("leave".equalsIgnoreCase(kqReportFieldComInfo.getFieldname())&&leaveRules.size()==0){
          continue;
        }
        title = new HashMap<>();
        String unitType = KQReportBiz.getUnitType(kqReportFieldComInfo, user);
        if(unitType.length()>0){
          title.put("title", SystemEnv.getHtmlLabelNames(kqReportFieldComInfo.getFieldlabel(), user.getLanguage())+ "(" + unitType + ")");
        }else{
          title.put("title", SystemEnv.getHtmlLabelNames(kqReportFieldComInfo.getFieldlabel(), user.getLanguage()));
        }
        title.put("width",30*256);
        this.lsFieldDataKey.add(kqReportFieldComInfo.getFieldname());
        mapChildColumnInfo = this.getChildColumnsInfo(kqReportFieldComInfo.getFieldname(),user);
        childColumns = (List<Object>)mapChildColumnInfo.get("childColumns");
        if(childColumns.size()>0) {//跨列width取子列的width
          title.put("children", childColumns);
          title.put("colSpan",childColumns.size());
        }else{
          title.put("rowSpan", 3);
        }
        titleList.add(title);
      }
      sheet.put("titleList", titleList);

      // 没有权限的人最大只支持查询本季
      Map<String, String> getRealDate = new KQReportBiz().realDate(fromDate, toDate, user, "2");
      fromDate = getRealDate.get("fromDate");
      toDate = getRealDate.get("toDate");
      if("-1".equals(fromDate) || "-1".equals(toDate)) {
        retmap.put("status", "1");
        return retmap;
      }
      List<List> paramLists = new ArrayList<>();
      List<Object> paramList = null;
      String forgotBeginWorkCheck_field = " b.forgotbeginworkcheck ";

      if(rs.getDBType().equalsIgnoreCase("oracle")&&!Util.null2String(rs.getOrgindbtype()).equals("dm")&&!Util.null2String(rs.getOrgindbtype()).equals("st")) {
        forgotBeginWorkCheck_field = " nvl(b.forgotBeginWorkCheck,0)  ";
      }else if((rs.getDBType()).equalsIgnoreCase("mysql")){
        forgotBeginWorkCheck_field = " ifnull(b.forgotBeginWorkCheck,0) ";
      }else {
        forgotBeginWorkCheck_field = " isnull(b.forgotBeginWorkCheck,0) ";
      }

      String backFields = " ufd.tname,zm.sjycqts as sjycqts, zm.sjycqss as sjycqss, zm.sjdksc as sjdksc," +
              " a.id,a.lastname,a.subcompanyid1 as subcompanyid,a.departmentid, a.workcode,b.jobtitle,a.dsporder," +
              " b.kqdate, b.workdays,b.workMins,b.serialid, b.attendancedays,b.attendanceMins,b.beLate," +
              " b.beLateMins,b.graveBeLate,b.graveBeLateMins,b.leaveEearly,b.leaveEarlyMins,b.graveLeaveEarly," +
              " b.graveLeaveEarlyMins,b.absenteeism,b.signdays,b.signmins, "+
              " b.absenteeismMins ,(b.forgotCheck+"+forgotBeginWorkCheck_field+") forgotCheck, "+
              "   CASE \n" +
              "        WHEN absenteeismMins IS NULL THEN 0\n" +
              "        WHEN absenteeismMins = 0 THEN 0\n" +
              "        WHEN absenteeismMins / 60.0 <= 3 THEN 0.5\n" +
              "\t\tELSE  1\n" +
              "    END AS kgtsqz ";
      String sqlFrom = " from hrmresource a JOIN kq_format_total b ON a.id= b.resourceid " +
              "LEFT JOIN uf_kqsjcqjsglb zm ON zm.xm = a.id AND zm.rq = b.kqdate " +
              "left join uf_first_dept ufd on ufd.deptid=a.departmentid " +
              " WHERE b.kqdate >='"+fromDate+"' and b.kqdate <='"+toDate+"'";
      String sqlWhere = rightSql;
      if(subCompanyId.length()>0){
        sqlWhere +=" and a.subcompanyid1 in("+KQReportBiz.splitParamStr(subCompanyId)+") ";
        for(String bean : subCompanyId.split(",")) {
          paramList = new ArrayList<>();
          paramList.add(bean);
          paramLists.add(paramList);
        }
      }

      if(departmentId.length()>0){
        sqlWhere +=" and a.departmentid in("+KQReportBiz.splitParamStr(departmentId)+") ";
        for(String bean : departmentId.split(",")) {
          paramList = new ArrayList<>();
          paramList.add(bean);
          paramLists.add(paramList);
        }
      }

      if(resourceId.length()>0){
        sqlWhere +=" and a.id in("+KQReportBiz.splitParamStr(resourceId)+") ";
        for(String bean : resourceId.split(",")) {
          paramList = new ArrayList<>();
          paramList.add(bean);
          paramLists.add(paramList);
        }
      }

      if(viewScope.equals("4")){//我的下属
        if(allLevel.equals("1")){//所有下属
          sqlWhere+=" and a.managerstr like '%,"+user.getUID()+",%'";
        }else{
          sqlWhere+=" and a.managerid="+user.getUID();//直接下属
        }
      }
      if (!"1".equals(isNoAccount)) {
        sqlWhere += " and a.loginid is not null "+(rs.getDBType().equals("oracle")?"":" and a.loginid<>'' ");
      }

      if(status.length()>0){
        if (!status.equals("8") && !status.equals("9")) {
          sqlWhere += " and a.status = ?";
          paramList = new ArrayList<>();
          paramList.add(status);
          paramLists.add(paramList);
        }else if (status.equals("8")) {
          sqlWhere += " and (a.status = 0 or a.status = 1 or a.status = 2 or a.status = 3) ";
        }
      }
      String orderBy = " order by a.dsporder asc, a.lastname asc , b.kqDate asc ";
      String descOrderBy = " order by a.dsporder desc, a.lastname desc ";
      sql = "select "+backFields + sqlFrom  + sqlWhere+orderBy;

      // #1475814-概述：满足考勤报分部部门显示及导出时显示全路径
      String fullPathMainKey = "show_full_path";
      String isShowFullPath = Util.null2String(kqSettingsComInfo.getMain_val(fullPathMainKey),"0");

      // 获取补卡次数
      RecordSet rsTemp = new RecordSet();
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
      Map<String, Set<String>> bdkSetMap = new HashMap<>();
//      rsTemp.execute("select userid, signdate, signtime from hrmschedulesign where signfrom like 'card%' and signfrom != 'card'" +
//              " and signdate >= '" + fromDate + "' and signdate <= '" + toDate + "'");
      String bkSql = "select a.* from \n" +
              "(SELECT a1.yg as userid, a1.kqrq as signdate, a1.bksj as signtime, a2.requestId FROM formtable_main_40_dt1 a1, formtable_main_40 a2 WHERE a1.mainid = a2.id) a,\n" +
              "workflow_requestbase b \n" +
              "WHERE a.requestId = b.requestId and b.currentnodetype = 3 \n" +
              "and a.signdate >= '" + fromDate + "' and a.signdate <= '" + toDate + "'";
      rsTemp.execute(bkSql);
      while (rsTemp.next()) {
        String id = rsTemp.getString("userid");
        String signdate = rsTemp.getString("signdate");
        String signtime = rsTemp.getString("signtime");
        if (StringUtils.isEmpty(id) || StringUtils.isEmpty(signdate) || StringUtils.isEmpty(signtime)) {
          continue;
        }
        if (signtime.length() == 5) {
          signtime = signtime + ":00";
        }
        String keyTemp = id + "_" + signdate;
        Set<String> bdkSet = new HashSet<>();
        if ((!CollectionUtils.isEmpty(bdkSetMap)) && bdkSetMap.containsKey(keyTemp)) {
          bdkSet = bdkSetMap.get(keyTemp);
        }
        LocalTime time = LocalTime.parse(signtime, formatter);
        int hour = time.getHour(); // 提取小时
        bdkSet.add(String.valueOf(hour));
        bdkSetMap.put(keyTemp, bdkSet);
      }

      Map<String,String> serialdata = new HashMap<>();
      boolean isneedcal = KQSettingsBiz.getKqformatAccurate();
      params.put("isneedcal",isneedcal?"1":"0");
      Map<String,Object> flowData = kqReportBiz.getDailyFlowData(params,user);
      rs.executeQuery(sql, paramLists);
      while (rs.next()) {
        data = new ArrayList<>();
        String id = rs.getString("id");
        String kqdate = rs.getString("kqdate");
        String tmpkey = id+"|"+kqdate+"|";
//        Map<String,Object> signDetailInfo = this.getSignDetailInfo(id,kqdate);

        for (int fieldDataKeyIdx =0;fieldDataKeyIdx<lsFieldDataKey.size();fieldDataKeyIdx++) {
          String fieldName = lsFieldDataKey.get(fieldDataKeyIdx);
          String fieldid =  KQReportFieldComInfo.field2Id.get(fieldName);
          String fieldValue = "";
          if(fieldName.equals("subcompany")){
            String tmpSubcompanyId = Util.null2String(rs.getString("subcompanyid"));
            if(tmpSubcompanyId.length()==0){
              tmpSubcompanyId =  Util.null2String(resourceComInfo.getSubCompanyID(id));
            }

            fieldValue = "1".equals(isShowFullPath) ?
                    SubCompanyComInfo.getSubcompanyRealPath(tmpSubcompanyId, "/", "0") :
                    subCompanyComInfo.getSubCompanyname(tmpSubcompanyId);

            // fieldValue = subCompanyComInfo.getSubCompanyname(tmpSubcompanyId);
          }else if(fieldName.equals("department")){
            String tmpDepartmentId = Util.null2String(rs.getString("departmentid"));
            if(tmpDepartmentId.length()==0){
              tmpDepartmentId =  Util.null2String(resourceComInfo.getDepartmentID(id));
            }

            fieldValue = "1".equals(isShowFullPath) ?
                    departmentComInfo.getDepartmentRealPath(tmpDepartmentId, "/", "0") :
                    departmentComInfo.getDepartmentname(tmpDepartmentId);

            // fieldValue = departmentComInfo.getDepartmentname(tmpDepartmentId);
          }else if(fieldName.equals("jobtitle")){
            String tmpJobtitleId = Util.null2String(rs.getString("jobtitle"));
            if(tmpJobtitleId.length()==0){
              tmpJobtitleId =  Util.null2String(resourceComInfo.getJobTitle(id));
            }
            fieldValue = jobTitlesComInfo.getJobTitlesname(tmpJobtitleId);
          } else if(fieldName.equals("serialid")){
            String serialid = Util.null2String(rs.getString("serialid"));
            if(serialid.length()>0){
//              fieldValue = Util.formatMultiLang(shiftManagementToolKit.getShiftOnOffWorkSections(serialid, user.getLanguage()));

              if(null != serialdata && serialdata.containsKey(serialid)){
                fieldValue = serialdata.get(serialid);
              }else{
                String tmpserialname = Util.formatMultiLang(shiftManagementToolKit.getShiftOnOffWorkSections(serialid, user.getLanguage()));
                fieldValue = tmpserialname;
                serialdata.put(serialid,tmpserialname);
              }
            }
          } else if(fieldName.equals("signin1")){
            fieldValue = Util.null2String(flowData.get(tmpkey+"signintime1"));
            data.add(fieldValue);
            fieldValue = Util.null2String(flowData.get(tmpkey+"signinstatus1"));
            data.add(fieldValue);
            continue;
          } else if(fieldName.equals("signin2")){
            fieldValue = Util.null2String(flowData.get(tmpkey+"signintime2"));
            data.add(fieldValue);
            fieldValue = Util.null2String(flowData.get(tmpkey+"signinstatus2"));
            data.add(fieldValue);
            continue;
          } else if(fieldName.equals("signin3")){
            fieldValue = Util.null2String(flowData.get(tmpkey+"signintime3"));
            data.add(fieldValue);
            fieldValue = Util.null2String(flowData.get(tmpkey+"signinstatus3"));
            data.add(fieldValue);
            continue;
          } else if(fieldName.equals("signout1")){
            fieldValue = Util.null2String(flowData.get(tmpkey+"signouttime1"));
            data.add(fieldValue);
            fieldValue = Util.null2String(flowData.get(tmpkey+"signoutstatus1"));
            data.add(fieldValue);
            continue;
          } else if(fieldName.equals("signout2")){
            fieldValue = Util.null2String(flowData.get(tmpkey+"signouttime2"));
            data.add(fieldValue);
            fieldValue = Util.null2String(flowData.get(tmpkey+"signoutstatus2"));
            data.add(fieldValue);
            continue;
          } else if(fieldName.equals("signout3")){
            fieldValue = Util.null2String(flowData.get(tmpkey+"signouttime3"));
            data.add(fieldValue);
            fieldValue = Util.null2String(flowData.get(tmpkey+"signoutstatus3"));
            data.add(fieldValue);
            continue;
          } else if (fieldName.equals("sjycqss") || fieldName.equals("sjdksc")) {
            fieldValue = Util.null2String(rs.getString(fieldName));
            data.add(fieldValue);
            continue;
          } else if (fieldName.equals("bkcsqz")) {
            Set<String> strings = bdkSetMap.get(id + "_" + kqdate);
            if (CollectionUtils.isEmpty(strings)) {
              fieldValue = "0";
            } else {
              if (strings.size() <= 2) {
                fieldValue = String.valueOf(strings.size());
              } else {
                fieldValue = "2";
              }
            }
            data.add(fieldValue);
            continue;
          } else if(fieldName.equals("leave")){
            //请假
            List<Map<String, Object>> allLeaveRules = KQLeaveRulesBiz.getAllLeaveRules();
            if (("1").equals(leavetype_is_on)) {
              KQLeaveRulesComInfo kqLeaveRulesComInfo = new KQLeaveRulesComInfo();
              for (int i = allLeaveRules.size() - 1; i >= 0; i--) {
                Map<String, Object> leaveRule = allLeaveRules.get(i);
                String leaveId = Util.null2String(leaveRule.get("id"));
                boolean flag = KQLeaveRulesBiz.filterSubLeaveRule(kqLeaveRulesComInfo, user, leaveId);
                if (flag) {
                  allLeaveRules.remove(i);
                }
              }
            }
            Map<String, Object> leaveRule = null;
            for(int i=0;allLeaveRules!=null&&i<allLeaveRules.size();i++){
              leaveRule = (Map<String, Object>)allLeaveRules.get(i);
              String flowType = Util.null2String("leaveType_"+leaveRule.get("id"));
              fieldValue = Util.null2String(flowData.get(id+"|"+kqdate+"|"+flowType));
              String flowLeaveBackType = Util.null2String("leavebackType_" + leaveRule.get("id"));
              String leavebackData = Util.null2s(Util.null2String(flowData.get(id + "|" + kqdate + "|" + flowLeaveBackType)), "0.0");
              String b_flowLeaveData = "";
              String flowLeaveData = "";
              try {
                //以防止出现精度问题
                if (fieldValue.length() == 0) {
                  fieldValue = "0.0";
                }
                if (leavebackData.length() == 0) {
                  leavebackData = "0.0";
                }
                BigDecimal b_leaveData = new BigDecimal(fieldValue);
                BigDecimal b_leavebackData = new BigDecimal(leavebackData);
                b_flowLeaveData = b_leaveData.subtract(b_leavebackData).toString();
                if(Util.getDoubleValue(b_flowLeaveData, -1) < 0){
                  b_flowLeaveData = "0.0";
                }

              } catch (Exception e) {
                writeLog("ExportDailyExcelCmd:fieldValue" + fieldValue + ":leavebackData:" + leavebackData + ":" + e);
              }
              //考虑下冻结的数据
              if (b_flowLeaveData.length() > 0) {
                flowLeaveData = KQDurationCalculatorUtil.getDurationRound(b_flowLeaveData);
              } else {
                flowLeaveData = KQDurationCalculatorUtil.getDurationRound(Util.null2String(Util.getDoubleValue(fieldValue, 0.0) - Util.getDoubleValue(leavebackData, 0.0)));
              }
              fieldValue = flowLeaveData;

              data.add(fieldValue);
            }
          }else if(fieldName.equals("overtime")){
            fieldValue = KQDurationCalculatorUtil.getDurationRound(Util.null2String(flowData.get(id +"|"+kqdate+ "|workingDayOvertime_nonleave")));
            data.add(getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(KQReportFieldComInfo.field2Id.get("workingDayOvertime_nonleave"))));

            fieldValue = KQDurationCalculatorUtil.getDurationRound(Util.null2String(flowData.get(id +"|"+kqdate+ "|restDayOvertime_nonleave")));
            data.add(getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(KQReportFieldComInfo.field2Id.get("restDayOvertime_nonleave"))));

            fieldValue = KQDurationCalculatorUtil.getDurationRound(Util.null2String(flowData.get(id +"|"+kqdate+ "|holidayOvertime_nonleave")));
            data.add(getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(KQReportFieldComInfo.field2Id.get("holidayOvertime_nonleave"))));

            fieldValue = KQDurationCalculatorUtil.getDurationRound(Util.null2String(flowData.get(id +"|"+kqdate+ "|workingDayOvertime_4leave")));
            data.add(getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(KQReportFieldComInfo.field2Id.get("workingDayOvertime_4leave"))));

            fieldValue = KQDurationCalculatorUtil.getDurationRound(Util.null2String(flowData.get(id +"|"+kqdate+ "|restDayOvertime_4leave")));
            data.add(getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(KQReportFieldComInfo.field2Id.get("restDayOvertime_4leave"))));

            fieldValue = KQDurationCalculatorUtil.getDurationRound(Util.null2String(flowData.get(id +"|"+kqdate+ "|holidayOvertime_4leave")));
            data.add(getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(KQReportFieldComInfo.field2Id.get("holidayOvertime_4leave"))));

            double workingDayOvertime_4leave = Util.getDoubleValue(Util.null2String(flowData.get(id+"|"+kqdate+"|workingDayOvertime_4leave")));
            workingDayOvertime_4leave = workingDayOvertime_4leave<0?0:workingDayOvertime_4leave;
            double restDayOvertime_4leave = Util.getDoubleValue(Util.null2String(flowData.get(id+"|"+kqdate+"|restDayOvertime_4leave")));
            restDayOvertime_4leave = restDayOvertime_4leave<0?0:restDayOvertime_4leave;
            double holidayOvertime_4leave = Util.getDoubleValue(Util.null2String(flowData.get(id+"|"+kqdate+"|holidayOvertime_4leave")));
            holidayOvertime_4leave = holidayOvertime_4leave<0?0:holidayOvertime_4leave;

            double workingDayOvertime_nonleave = Util.getDoubleValue(Util.null2String(flowData.get(id+"|"+kqdate+"|workingDayOvertime_nonleave")));
            workingDayOvertime_nonleave = workingDayOvertime_nonleave<0?0:workingDayOvertime_nonleave;
            double restDayOvertime_nonleave = Util.getDoubleValue(Util.null2String(flowData.get(id+"|"+kqdate+"|restDayOvertime_nonleave")));
            restDayOvertime_nonleave = restDayOvertime_nonleave<0?0:restDayOvertime_nonleave;
            double holidayOvertime_nonleave = Util.getDoubleValue(Util.null2String(flowData.get(id+"|"+kqdate+"|holidayOvertime_nonleave")));
            holidayOvertime_nonleave = holidayOvertime_nonleave<0?0:holidayOvertime_nonleave;
            fieldValue = KQDurationCalculatorUtil.getDurationRound(String.valueOf(workingDayOvertime_4leave+restDayOvertime_4leave+holidayOvertime_4leave+
                    workingDayOvertime_nonleave+restDayOvertime_nonleave+holidayOvertime_nonleave));
            data.add(getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(KQReportFieldComInfo.field2Id.get("overtimeTotal"))));
            continue;
          }else if(fieldName.equals("businessLeave") || fieldName.equals("officialBusiness")){
            String businessLeaveData = Util.null2s(Util.null2String(flowData.get(id+"|"+kqdate+"|"+fieldName)),"0.0");
            String backType = fieldName+"_back";
            String businessLeavebackData = Util.null2s(Util.null2String(flowData.get(id+"|"+kqdate+"|"+backType)),"0.0");
            String businessLeave = "";
            try{
              //以防止出现精度问题
              if(businessLeaveData.length() == 0){
                businessLeaveData = "0.0";
              }
              if(businessLeavebackData.length() == 0){
                businessLeavebackData = "0.0";
              }
              BigDecimal b_businessLeaveData = new BigDecimal(businessLeaveData);
              BigDecimal b_businessLeavebackData = new BigDecimal(businessLeavebackData);
              businessLeave = b_businessLeaveData.subtract(b_businessLeavebackData).toString();
              if(Util.getDoubleValue(businessLeave, -1) < 0){
                businessLeave = "0.0";
              }
            }catch (Exception e){
            }
            fieldValue = KQDurationCalculatorUtil.getDurationRound(businessLeave);
          }else if(fieldName.equals("kqdate")){
            fieldValue=kqdate+" "+com.engine.portal.util.DateUtil.getDayWeekOfDate1(DateUtil.parseToDate(kqdate));
          }  else {
            fieldValue = Util.null2String(rs.getString(fieldName));
            fieldValue = getFieldValueByUnitType(fieldValue,kqReportFieldComInfo.getUnittype(fieldid));
          }

          if(!fieldName.equals("leave")) {
            fieldValue = Util.formatMultiLang(fieldValue, "" + user.getLanguage());
            data.add(fieldValue);
          }
        }
        dataList.add(data);
      }
      sheet.put("dataList", dataList);
      sheet.put("constraintList",constraintList);
      sheet.put("createFile", "1");
      lsSheet.add(sheet);

      workbook.put("sheet", lsSheet);
      String fileName = 	SystemEnv.getHtmlLabelName(390352, user.getLanguage())+" "+fromDate+" "+toDate;;
      workbook.put("fileName", fileName);
      ExcelUtil ExcelUtil = new ExcelUtil();
      Map<String,Object> exportMap= ExcelUtil.export(workbook,request,response);
      retmap.putAll(exportMap);
      retmap.put("status", "1");
    } catch (Exception e) {
      retmap.put("status", "-1");
      retmap.put("message", SystemEnv.getHtmlLabelName(382661, user.getLanguage()));
      writeLog(e);
    }
    return retmap;
  }

  private Map<String,Object> getChildColumnsInfo(String parentid, User user){
    Map<String,Object> returnMap = new HashMap<>();
    List<Object> titleList = new ArrayList<>();
    Map<String,Object> title = null;
    KQSettingsComInfo kqSettingsComInfo = new KQSettingsComInfo();
    String leavetype_is_on = Util.null2String(kqSettingsComInfo.getMain_val("leavetype_is_on"),"0");
    if(parentid.equals("leave")){
      KQLeaveRulesBiz kqLeaveRulesBiz = new KQLeaveRulesBiz();
      List<Map<String, Object>> leaveRules = kqLeaveRulesBiz.getAllLeaveRules();
      if (("1").equals(leavetype_is_on)) {
        KQLeaveRulesComInfo kqLeaveRulesComInfo = new KQLeaveRulesComInfo();
        for (int i = leaveRules.size() - 1; i >= 0; i--) {
          Map<String, Object> leaveRule = leaveRules.get(i);
          String leaveId = Util.null2String(leaveRule.get("id"));
          boolean flag = kqLeaveRulesBiz.filterSubLeaveRule(kqLeaveRulesComInfo, user, leaveId);
          if (flag) {
            leaveRules.remove(i);
          }
        }
      }
      for(int i=0;leaveRules!=null&&i<leaveRules.size();i++){
        Map<String, Object> leaveRule = leaveRules.get(i);
        String name = Util.formatMultiLang(Util.null2String(leaveRule.get("name")),""+user.getLanguage());
        String unitType = Util.null2String(leaveRule.get("unitType"));
        title = new HashMap<>();
        title.put("title",name+"("+
                ((KQUnitBiz.isLeaveHour(unitType))?SystemEnv.getHtmlLabelName(391, user.getLanguage()):SystemEnv.getHtmlLabelName(1925, user.getLanguage()))+")");
        title.put("width",30*256);
        titleList.add(title);

      }
    }else if(parentid.equals("overtime")){
      String[] overtimeChild = {"overtime_nonleave","overtime_4leave","overtimeTotal"};
      for(int i=0;i<overtimeChild.length;i++){
        String id = overtimeChild[i];
        title = new HashMap();
        String fieldlabel = "";
        if("overtime_nonleave".equalsIgnoreCase(id)){
          fieldlabel = "125805";
          title.put("title", SystemEnv.getHtmlLabelNames(fieldlabel, user.getLanguage()));
          title.put("rowSpan","2");
        }else if("overtime_4leave".equalsIgnoreCase(id)){
          fieldlabel = "125804";
          title.put("title", SystemEnv.getHtmlLabelNames(fieldlabel, user.getLanguage()));
          title.put("rowSpan","2");
        }else{
          fieldlabel = "523";
          title.put("showDetial","1");
          String unitType = (KQOvertimeRulesBiz.getMinimumUnit()==3 || KQOvertimeRulesBiz.getMinimumUnit()==5 ||KQOvertimeRulesBiz.getMinimumUnit()==6)?"2":"1";
          String unitTypeName = "";
          if(Util.null2String(unitType).length()>0){
            if(unitType.equals("1")){
              unitTypeName=SystemEnv.getHtmlLabelName(1925, user.getLanguage());
            }else if(unitType.equals("2")){
              unitTypeName=SystemEnv.getHtmlLabelName(391, user.getLanguage());
            }else if(unitType.equals("3")){
              unitTypeName=SystemEnv.getHtmlLabelName(18083, user.getLanguage());
            }
          }
          title.put("title", SystemEnv.getHtmlLabelNames(fieldlabel, user.getLanguage())+ "(" + unitTypeName + ")");
        }
        Map<String,Object> mapChildColumnInfo = getChildColumnsInfo(id, user);
        int childWidth = 65;
        List<Object> childColumns = (List<Object>)mapChildColumnInfo.get("childColumns");
        if(childColumns.size()>0) {//跨列width取子列的width
          title.put("children", childColumns);
          childWidth = Util.getIntValue(Util.null2String(mapChildColumnInfo.get("sumChildColumnWidth")),65);
        }
        title.put("width", childWidth+"");
        titleList.add(title);
      }
    } else{
      KQReportFieldComInfo kqReportFieldComInfo = new KQReportFieldComInfo();
      while (kqReportFieldComInfo.next()){
        if(kqReportFieldComInfo.getParentid().equals(parentid)) {
          if(!kqReportFieldComInfo.getReportType().equals("daily"))continue;
          title = new HashMap<>();
          title.put("title",SystemEnv.getHtmlLabelNames(kqReportFieldComInfo.getFieldlabel(), user.getLanguage())+
                  (KQReportBiz.getUnitType(kqReportFieldComInfo, user).length()>0?"("+ KQReportBiz.getUnitType(kqReportFieldComInfo, user)+")":""));
          title.put("width",30*256);
          titleList.add(title);
        }
      }
    }
    returnMap.put("childColumns",titleList);
    return returnMap;
  }

  public Map<String, Object> getSignDetailInfo(String resourceId, String kqDate){
    Map<String, Object> data = new HashMap<>();
    Map<String,Object> signStatusInfo = null;
    RecordSet rs = new RecordSet();
    String sql = "";
    KQTimesArrayComInfo kqTimesArrayComInfo = new KQTimesArrayComInfo();
    try{
      sql = " select kqdate,resourceid,serialid,serialnumber,workbegindate,workbegintime, " +
              " workenddate,workendtime,workmins,signindate,signintime,signoutdate,signouttime, \n" +
              " attendanceMins,belatemins,graveBeLateMins,leaveearlymins,graveLeaveEarlyMins,absenteeismmins,forgotcheckMins,forgotBeginWorkCheckMins," +
              " leaveMins,leaveInfo,evectionMins,outMins,signinid,signoutid \n" +
              " from kq_format_detail b \n" +
              " where resourceid = " + resourceId + " and kqdate ='" + kqDate + "' \n" +
              " order by serialnumber \n";
      rs.execute(sql);
      while (rs.next()) {
        String resourceid = Util.null2String(rs.getString("resourceid"));
        String kqdate = Util.null2String(rs.getString("kqdate"));
        String serialid = Util.null2String(rs.getString("serialid"));
        int serialnumber  = rs.getInt("serialnumber")+1;
        String workbegindate = Util.null2String(rs.getString("workbegindate")).trim();
        String workbegintime = Util.null2String(rs.getString("workbegintime")).trim();
        String workenddate = Util.null2String(rs.getString("workenddate")).trim();
        String workendtime = Util.null2String(rs.getString("workendtime")).trim();
        int workMins = rs.getInt("workMins");
        String signintime = Util.null2String(rs.getString("signintime")).trim();
        String signouttime = Util.null2String(rs.getString("signouttime")).trim();
        int attendanceMins = rs.getInt("attendanceMins");
        String beLateMins = Util.null2String(rs.getString("beLateMins")).trim();
        String graveBeLateMins = Util.null2String(rs.getString("graveBeLateMins")).trim();
        String leaveEarlyMins= Util.null2String(rs.getString("leaveEarlyMins")).trim();
        String graveLeaveEarlyMins= Util.null2String(rs.getString("graveLeaveEarlyMins")).trim();
        String absenteeismMins= Util.null2String(rs.getString("absenteeismMins")).trim();
        String forgotCheckMins = Util.null2String(rs.getString("forgotcheckMins")).trim();
        String forgotBeginWorkCheckMins = Util.null2String(rs.getString("forgotBeginWorkCheckMins")).trim();
        String signinid = Util.null2String(rs.getString("signinid")).trim();
        String signoutid = Util.null2String(rs.getString("signoutid")).trim();
        int leaveMins = rs.getInt("leaveMins");
        String leaveInfo = Util.null2String(rs.getString("leaveInfo"));
        int evectionMins = rs.getInt("evectionMins");
        int outMins = rs.getInt("outMins");


        if(serialid.length()>0){
          if (workbegintime.length() > 0) {
            signStatusInfo = new HashMap();
            signStatusInfo.put("workdate",workbegindate);
            signStatusInfo.put("worktime",workbegintime);
            signStatusInfo.put("beLateMins",beLateMins);
            signStatusInfo.put("forgotBeginWorkCheckMins",forgotBeginWorkCheckMins);
            signStatusInfo.put("graveBeLateMins",graveBeLateMins);
            signStatusInfo.put("absenteeismMins",absenteeismMins);
            signStatusInfo.put("leaveMins",leaveMins);
            signStatusInfo.put("leaveInfo",leaveInfo);
            signStatusInfo.put("evectionMins",evectionMins);
            signStatusInfo.put("outMins",outMins);

            data.put("signintime"+serialnumber, signintime.length()==0?SystemEnv.getHtmlLabelName(25994, user.getLanguage()):signintime);
            data.put("signinstatus"+serialnumber, KQReportBiz.getSignStatus(signStatusInfo,user,"on"));
          }

          if (workendtime.length() > 0) {
            signStatusInfo = new HashMap();
            signStatusInfo.put("workdate",workenddate);
            signStatusInfo.put("worktime",kqTimesArrayComInfo.turn48to24Time(workendtime));
            signStatusInfo.put("leaveEarlyMins",leaveEarlyMins);
            signStatusInfo.put("graveLeaveEarlyMins",graveLeaveEarlyMins);
            signStatusInfo.put("forgotCheckMins",forgotCheckMins);
            signStatusInfo.put("forgotBeginWorkCheckMins",forgotBeginWorkCheckMins);
            signStatusInfo.put("absenteeismMins",absenteeismMins);
            signStatusInfo.put("leaveMins",leaveMins);
            signStatusInfo.put("leaveInfo",leaveInfo);
            signStatusInfo.put("evectionMins",evectionMins);
            signStatusInfo.put("outMins",outMins);

            data.put("signouttime"+serialnumber, signouttime.length()==0?SystemEnv.getHtmlLabelName(25994, user.getLanguage()):signouttime);
            data.put("signoutstatus"+serialnumber, KQReportBiz.getSignStatus(signStatusInfo,user,"off"));
          }
        }else{
          if(workMins>0){
            //弹性工时打卡时间取自签到签退数据
          }
          signStatusInfo = new HashMap();
          signStatusInfo.put("leaveMins",leaveMins);
          signStatusInfo.put("leaveInfo",leaveInfo);
          signStatusInfo.put("evectionMins",evectionMins);
          signStatusInfo.put("outMins",outMins);

          if(signinid.length() > 0){
            data.put("signintime"+serialnumber, signintime.length()==0?SystemEnv.getHtmlLabelName(25994, user.getLanguage()):signintime);
            data.put("signinstatus"+serialnumber, KQReportBiz.getSignStatus(signStatusInfo,user,"on"));
            if(signoutid.length() > 0){
              data.put("signouttime"+serialnumber, signouttime.length()==0?SystemEnv.getHtmlLabelName(25994, user.getLanguage()):signouttime);
              data.put("signoutstatus"+serialnumber, KQReportBiz.getSignStatus(signStatusInfo,user,"off"));
            }
          }else{
            data.put("signinstatus"+serialnumber, KQReportBiz.getSignStatus(signStatusInfo,user,"on"));
          }
        }
      }
    }catch (Exception e){
      writeLog(e);
    }
    return data;
  }

  private String getFieldValueByUnitType(String fieldValue,String unittype){
    if (Util.null2String(unittype).length() > 0) {
      if (fieldValue.length() == 0) {
        fieldValue = "0";
      } else {
        if (unittype.equals("2")) {
          fieldValue = KQDurationCalculatorUtil.getDurationRound(("" + (Util.getDoubleValue(fieldValue) / 60.0)));
        }
      }
    }
    return fieldValue;
  }

  @Override
  public BizLogContext getLogContext() {
    return null;
  }
}
